﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using SocketAPI;
using System.Threading;
using System.Collections;
using System.IO;
using System.Windows.Forms;
using SocketAPI.EventArguments;

namespace socketAPI
{
    public class SocketServerConn
    {
        // Incoming data from the client.
        private string data = null;
        private int threads = 1;
        public static ArrayList clientSockets = new ArrayList();
        public static ArrayList clientThreads = new ArrayList();
        public static ArrayList clientClasses = new ArrayList();
        public static int activeClients = 0;
        private string serverPassword = "";
        public static Socket calculationHost;
        private string ipStr = "";
        public delegate void addLogCallback(string data);
        public delegate void setStatusCallback(string newStatus);
        private Thread msgThr;
        public static ArrayList controllers = new ArrayList();
        public static IPEndPoint endPoint;
        public static ServerSettings serverSettings = new ServerSettings();
        public void StartListening()
        {
            // Data buffer for incoming data.
            byte[] bytes = new Byte[1024];

            // Establish the local endpoint for the socket.
            // Dns.GetHostName returns the name of the 
            // host running the application.
            IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipv4Address = new IPAddress(new byte[4] { 0, 0, 0, 0 } );
            foreach (IPAddress address in hostEntry.AddressList)
            {
                string addr = address.ToString();
                if (addr.Contains(":") == false)
                {
                    ipv4Address = address;
                    ipStr = addr;
                }
            }
            #region askPort
            Console.WriteLine("Server Port [5555]:");
            string inp = Console.ReadLine();
            int setport = 5555;
            if (inp == "")
            {
                setport = 5555;
            }
            else
            {
                setport = int.Parse(inp);
            }
            #endregion
            IPEndPoint localEndPoint = new IPEndPoint(ipv4Address, setport);
            serverSettings.Address = ipv4Address.ToString();
            serverSettings.Port = setport.ToString();
            #region askLocation
            Console.WriteLine("Server Location [New Zealand]:");
            string setloc = Console.ReadLine();
            if (setloc == "")
            {
                serverSettings.Location = "New Zealand";
            }
            else
            {
                serverSettings.Location = setloc;
            }
            #endregion
            #region askType
            Console.WriteLine("Server Type [Normal]:");
            string settype = Console.ReadLine();
            if (settype == "")
            {
                serverSettings.Type = "Normal";
            }
            else
            {
                serverSettings.Type = settype;
            }
            #endregion
            #region askOptional
            Console.WriteLine("Server Optional Information []:");
            string setoptional = Console.ReadLine();
            if (setoptional == "")
            {
                serverSettings.Optional = "";
            }
            else
            {
                serverSettings.Optional = setoptional;
            }
            #endregion
            #region askOwner
            Console.WriteLine("Server Owner []:");
            string setowner = Console.ReadLine();
            if (setowner == "")
            {
                serverSettings.Owner = "";
            }
            else
            {
                serverSettings.Owner = setowner;
            }
            #endregion
            serverSettings.MaxPlayers = "Inf";
            Console.Clear();
            endPoint = localEndPoint;

            //DataArray 
            ArrayList dataLines = new ArrayList();

            // Create a TCP/IP socket.
            Socket listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            // Bind the socket to the local endpoint and 
            // listen for incoming connections.
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(10);
                SpecialConsole.Text.WriteLine("_______         ______  _______ _______ _______ _______ _______ _______  ______", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("   |    |     | |     \\ |______ |______ |______ |______ |______ |______ |_____/", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("   |    |_____| |_____/ |______ ______| |______ ______| ______| |______ |    \\_", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("                                                                         ", ConsoleColor.White);
                SpecialConsole.Text.WriteLine(" ______ _______ _______ _______", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("|  ____ |_____| |  |  | |______", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("|_____| |     | |  |  | |______", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("                                            ", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("_______ _______  ______ _    _ _______  ______", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("|______ |______ |_____/  \\  /  |______ |_____/", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("______| |______ |    \\_   \\/   |______ |    \\_", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("By Dean Gardiner", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("http://code.google.com/p/advancedflashengine - http://www.winmastergames.com", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("=============================================", ConsoleColor.White);
                SpecialConsole.Text.WriteLine("Red = Server Messages", ConsoleColor.Red);
                SpecialConsole.Text.WriteLine("Yellow = Client Messages", ConsoleColor.Yellow);
                SpecialConsole.Text.WriteLine("Green = AI Messages", ConsoleColor.Green);
                SpecialConsole.Text.WriteLine("Blue = Command Messages", ConsoleColor.Blue);
                SpecialConsole.Text.WriteLine("=============================================", ConsoleColor.White);
                // Send Heartbeat to Master Server.
                serverSettings.CurrentPlayers = clientThreads.Count.ToString();
                HeartBeatClient hbClass = new HeartBeatClient();
                Thread hbThread = new Thread(new ThreadStart(hbClass.runThread));
                hbThread.Start();
                // Start listening for connections.
                while (true)
                {
                    SpecialConsole.Text.WriteLine("Waiting for Connection on " + ipv4Address + ":" + localEndPoint.Port + "...", ConsoleColor.Red);
                    // Program is suspended while waiting for an incoming connection.
                    data = null;

                    // An incoming connection needs to be processed.
                    Socket tempClientSocketConnection = listener.Accept();
                    ClientSocketThread tempClient = new ClientSocketThread(tempClientSocketConnection, listener, threads, dataLines, clientSockets, Encoding.ASCII.GetBytes(serverPassword));
                    clientSockets.Add(tempClientSocketConnection);
                    Thread tempClientThread = new Thread(new ThreadStart(tempClient.runThread));
                    clientClasses.Add(tempClient);
                    tempClientThread.Start();
                    clientThreads.Add(tempClientThread);
                    Console.Title = "Todesesser Game Server - Active Clients: " + socketAPI.SocketServerConn.activeClients;
                    serverSettings.CurrentPlayers = clientThreads.Count.ToString();
                    hbClass.reStartUp();
                    hbClass.sendCurrentPlayers();
                    hbClass.reShutDown();
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

        public void StartClient(string host, int port, ListView drawLog, Label statusTxt, addLogCallback addLog, setStatusCallback setStatus) {
            setStatus("Trying to Connect...");
        // Data buffer for incoming data.
        byte[] bytes = new byte[1024];

        // Connect to a remote device.
        try {
            addLog("Created!");
            // Establish the remote endpoint for the socket.
            // This example uses port 11000 on the local computer.
            IPAddress ipAddress = Dns.GetHostByName(host).AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(ipAddress,port);

            // Create a TCP/IP  socket.
            Socket sender = new Socket(AddressFamily.InterNetwork, 
                SocketType.Stream, ProtocolType.Tcp );

            // Connect the socket to the remote endpoint. Catch any errors.
            messageReceiver msgRec = new messageReceiver(sender, remoteEP, addLog, setStatus);
            msgThr = new Thread(new ThreadStart(msgRec.runThread));
            msgThr.Start();

        } catch (Exception e) {
            drawLog.Items.Add(e.ToString());
        }
    }
    }
}
/// <summary>
/// Contains static text methods.
/// Put this in a separate class in your project.
/// </summary>
public static class TextTool
{
    /// <summary>
    /// Count occurrences of strings.
    /// </summary>
    public static int CountStringOccurrences(string text, string pattern)
    {
        // Loop through all instances of the string 'text'.
        int count = 0;
        int i = 0;
        while ((i = text.IndexOf(pattern, i)) != -1)
        {
            i += pattern.Length;
            count++;
        }
        return count;
    }
}